/**
 * @author haina.z@163.com
 * @brief Chip flash driver
 * @version V1.0
 */

/** Includes -----------------------------------------------------------------*/
#include "public_defs.h"
#include "apm32f10x_fmc.h"

/** Macros and constants -----------------------------------------------------*/
// #define FLASHDRIVER_RAM_ALIGN_4BYTES // 针对M3内核，不需要

/** Type definitions ---------------------------------------------------------*/

/** Private variable definitions (static) ------------------------------------*/

/** Function declarations (prototypes) ---------------------------------------*/

/** Public variable definitions ----------------------------------------------*/

/** Pre-compile check --------------------------------------------------------*/

/** Code ---------------------------------------------------------------------*/

void CspFlash_Read(uint32_t u32Address, uint8_t * pBuffer, uint16_t u16Length)
{
    uint16_t i;

    if ((u32Address % 4) || (u16Length % 4))
    {
        return;
    }

    #ifdef FLASHDRIVER_RAM_ALIGN_4BYTES
    if ((uint32_t)pBuffer & 0x3)
    {
        DataAlign4Bytes_t oAlign;
        for (i = 0; i < (u16Length/4); i++)
        {
            oAlign.u32Data = (*(__I uint32_t*) (u32Address + i*4));
            *pBuffer = oAlign.u8Data[0];pBuffer++;
            *pBuffer = oAlign.u8Data[1];pBuffer++;
            *pBuffer = oAlign.u8Data[2];pBuffer++;
            *pBuffer = oAlign.u8Data[3];pBuffer++;
        }
    }
    else
    #endif
    {
        for (i = 0; i < (u16Length/4); i++)
        {
            ((uint32_t *)pBuffer)[i] = (*(__I uint32_t*) (u32Address + i*4));
        }
    }
}

bool CspFlash_Write(uint32_t u32Address, uint8_t * pBuffer, uint16_t u16Length)
{
    volatile FMC_STATUS_T FLASHStatus = FMC_STATUS_COMPLETE;
    uint16_t i;

    if ((u32Address % 4) || (u16Length % 4))
    {
        return false;
    }

    FMC_Unlock();
    #ifdef FLASHDRIVER_RAM_ALIGN_4BYTES
    if ((uint32_t)pBuffer & 0x3)
    {
        DataAlign4Bytes_t oAlign;
        for (i = 0; i < (u16Length/4); i++)
        {
            oAlign.u8Data[0] = *pBuffer++;
            oAlign.u8Data[1] = *pBuffer++;
            oAlign.u8Data[2] = *pBuffer++;
            oAlign.u8Data[3] = *pBuffer++;
            FLASHStatus = FMC_ProgramWord((u32Address + i*4), oAlign.u32Data);
            if (FLASHStatus != FMC_STATUS_COMPLETE)
            {
                break;
            }
        }
    }
    else
    #endif
    {
        for (i = 0; i < (u16Length/4); i++)
        {
            FLASHStatus = FMC_ProgramWord((u32Address + i*4), ((uint32_t *)pBuffer)[i]);
            if (FLASHStatus != FMC_STATUS_COMPLETE)
            {
                break;
            }
        }
    }
    FMC_Lock();

    return (FLASHStatus == FMC_STATUS_COMPLETE) ? true : false;;
}

bool CspFlash_Erase(uint32_t u32Address)
{
    volatile FMC_STATUS_T FLASHStatus = FMC_STATUS_COMPLETE;

    FMC_Unlock();
    FLASHStatus = FMC_ErasePage(u32Address);
    FMC_Lock();

    return (FLASHStatus == FMC_STATUS_COMPLETE) ? true : false;
}

/******************************** End of file *********************************/
